package cn.maydaymemory.mastery.command.api;

import cn.maydaymemory.mastery.annotation.CommandHandler;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;

import java.lang.reflect.Method;

public class CommandStructureExecutor {
    private CommandStructure structure;
    private CommandSender sender;
    private Configuration language = new YamlConfiguration();
    private boolean helperEnable = true;

    CommandStructureExecutor(CommandStructure structure){
        this.structure=structure;
        structure.initHelper(language);
    }
    CommandStructureExecutor(CommandStructure structure,Configuration language){
        this.language = language;
        this.structure=structure;
        structure.initHelper(language);
    }

    public void excute(String name,String label,String[] args){
        if(sender==null) return;
        Configuration lang;
        if(language!=null) lang = language;
        else lang = new YamlConfiguration();
        try{
            boolean invoked=false;
            boolean format=true;
            boolean permit=false;
            if(name.equalsIgnoreCase("help")&&helperEnable){
                if(args==null||args.length<1){
                    sendHelp(1);
                    return;
                }
                sendHelp(Integer.valueOf(args[0]));
                return;
            }
            for(Method method:structure.getClass().getDeclaredMethods()){
                method.setAccessible(true);
                CommandHandler handler=method.getAnnotation(CommandHandler.class);
                if(method.isAnnotationPresent(CommandHandler.class)){
                    if(handler.name().equalsIgnoreCase(name)){
                        invoked=true;
                        if(sender.hasPermission(handler.permission())){
                            permit=true;
                            if(args!=null&&args.length==handler.parameters().length){
                                format=false;
                                if(handler.playerOnly()){
                                    if(sender instanceof Player){
                                        Player p = (Player) sender;
                                        structure.redefine(p,label,args,method);
                                        break;
                                    } else {
                                        sender.sendMessage(lang.getString("player-only","§cOnly players could use this command,")+"");
                                    }
                                }else{
                                    structure.redefine(sender,label,args,method);
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            CommandStructure child = getChildStructure(name);
            if(child!=null) {
                CommandStructureExecutor executor = structure.getChildStructureExecutor(child).sender(sender).language(language);
                if (args == null || args.length < 1) {
                    if (executor.helperEnable()) executor.sendHelp(1);
                    return;
                }
                if (args.length == 1) {
                    executor.excute(args[0], label, new String[0]);
                    return;
                }
                String[] par = new String[args.length - 1];
                System.arraycopy(args, 1, par, 0, args.length - 1);
                executor.excute(args[0], label, par);
                return;
            }

            if(!invoked){
                sender.sendMessage((lang.getString("wrong-command","§cYou've input a wrong sub-command: "+name)+"").replaceAll("%sub_command%",name));
                return;
            }

            if(!permit){
                sender.sendMessage(lang.getString("no-permission","§cYou don't have permission to do this.")+"");
                return;
            }
            if(format){
                sender.sendMessage(lang.getString("format","Parameters format went wrong.Please watch over help construction.")+"");
            }
        }catch (Exception e){
            sender.sendMessage(lang.getString("error","An error occurred when command was executed.")+"");
            Bukkit.getServer().getLogger().warning(e.getMessage());
            for (StackTraceElement s: e.getStackTrace()) Bukkit.getServer().getLogger().warning(s.toString());
        }
    }
    public CommandStructureExecutor helperEnable(boolean enable){
        helperEnable=enable;
        return this;
    }
    public boolean helperEnable(){
        return helperEnable;
    }

    public void sendHelp(int page){
        structure.sender = this.sender;
        structure.sendHelp(page);
    }

    public CommandStructureExecutor language(Configuration language){
        this.language = language;
        structure.initHelper(language);
        return this;
    }
    public Configuration language(){ return language; }

    public CommandStructureExecutor sender(CommandSender sender){
        this.sender=sender;
        return this;
    }
    public CommandSender sender(){ return sender; }

    public CommandStructure structure(){return structure;}

    public CommandStructure getChildStructure(String name){
        return structure.getChildStructure(name);
    }
}
